﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DLLToolsLibrary;
using CodeEditor;
using HelpWindow;
using System.IO;
using System.Reflection;
using HalconDotNet;
using System.Threading;
using System.Runtime.InteropServices;

namespace cube
{
    /// <summary>
    /// Struktur, beinhaltet Username und Userlevel
    /// </summary>
    struct userInfo
    {
        public String userName;
        public int userLevel;
    }
    /// <summary>
    /// Hauptform zur Verwaltung der geladenen Module
    /// </summary>
    public partial class cubeForm : Form
    {
       
        //Delegate für threadübergreifenden Zugriff auf Hauptform-Control
        delegate void editor_ExceptionThrownDelegate(object sender, System.Threading.ThreadExceptionEventArgs e);
        //ModuleListe die dynamisch geladene Formen enthält
        List<dynamic> moduleListe = new List<dynamic>();

        #region Formen des Hauptprogramms
        public userAccount userAccount;
        DllViewTree treeForm;
        Editor editor;
        userInfo currentUser;
        LoginFrm loginForm;
        HelpWindow.HelpWindow helpForm;
        public ErrorLogForm errorForm;
        #endregion

        #region Konstruktor und Shown-Methode zur Initialisierung des Hauptprogramms
        /// <summary>
        /// Hauptform Konstruktor
        /// </summary>
        public cubeForm(String[] args)
        {

            if (File.Exists("language.txt"))
            {
                Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(File.ReadAllText("language.txt"));
            }

            editor = new Editor();
            treeForm = new DllViewTree();
            currentUser = new userInfo();
            loginForm = new LoginFrm();
            helpForm = new HelpWindow.HelpWindow();
            errorForm = new ErrorLogForm();

            InitializeComponent();
            this.WindowState = FormWindowState.Maximized;
            editor.ExceptionThrown += new System.Threading.ThreadExceptionEventHandler(editor_ExceptionThrown);
            errorForm.ClosedClicked += new EventHandler<EventArgs>(errorForm_ClosedClicked);
            StatusButton_ErrorStatus.Image = imageList_ErrorLights.Images[0];
            //Falls ein User übergeben wurde das Passwort des übergebenen Users prüfen  
            if (args.Length > 1)
            {
                String pw_user = registryUserData.getUserData(args[0])[0];
                String pw_login = md5Encrypter.CreateMD5(args[1]);
                if (pw_login == pw_user)
                {
                    currentUser.userName = args[0];
                    currentUser.userLevel = Convert.ToInt32(registryUserData.getUserData(args[0])[1]);
                }
            }
        }
        /// <summary>
        /// Nach Initialisierung der Hauptform User anmelden und verfügbare Module laden
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cubeForm_Shown(object sender, EventArgs e)
        {
            if ((currentUser.userName == "")||(currentUser.userName == null))
            {
                if (DialogResult.Cancel == loginForm.ShowDialog())
                {
                    loginForm.Close();
                    this.Close();
                }
                else
                {
                    currentUser.userName = loginForm.User;
                    currentUser.userLevel = loginForm.UserLevel;
                }
            }
            userAccount = new userAccount(currentUser.userName, currentUser.userLevel);
            userAccount.UserLogedIn += userAccount_UserLogedIn;

            Application.DoEvents();

            treeForm.SetModulePath(Application.StartupPath + "\\Module");
            treeForm.TabText = Properties.Resources.ModuleTabText;
            treeForm.Show(dockPanelMain, DigitalRune.Windows.Docking.DockState.DockLeftAutoHide);
            showModulesMenuItem.Checked = false;
            editor.AutoHidePortion = 0.5;
            editor.Show(dockPanelMain, DigitalRune.Windows.Docking.DockState.DockRightAutoHide);

            loadModules(Application.StartupPath + "\\Module");

            helpForm.UpdateChildren(moduleListe);

            BuildViewMenuItems();

            userAccount_UserLogedIn(this, new userEventArgs(currentUser.userName, currentUser.userLevel));
        }
        #endregion

        #region Methoden und abonnierte Events aus anderen Formen

        /// <summary>
        /// Lädt Module vom Typ DockableForm in die ModuleListe und macht die Typen aus den Modulen
        /// im Moduleverzeichnis dem Skripter bekannt
        /// </summary>
        /// <param name="modulPath"></param>
        private void loadModules(String modulPath)
        {
            DirectoryInfo dI = new DirectoryInfo(modulPath);
            AppDomain.CurrentDomain.AppendPrivatePath(modulPath);
            
            foreach (FileInfo fI in dI.GetFiles())
            {
                Assembly lib;

                try
                {
                    lib = Assembly.LoadFrom(fI.FullName);
                }
                catch
                {
                    continue;
                }
                foreach (Type typ in lib.GetExportedTypes())
                {
                    //Macht dem Skripter die enthaltenen Typen alle bekannt, so dass auch vom Skripter aus
                    //auf die enthaltenen Methoden zugegriffen werden kann. Der Skripter lädt automatisch
                    //schon alle Typen aus dem Verzeichnis der Exe rein
                    editor.addLib(lib);
                    
                    //Instanzen der Formen der geladenen Module erstellen und anzeigen lassen
                    if (typ.BaseType == typeof(DigitalRune.Windows.Docking.DockableForm))
                    {
                        //Wir benutzen dynamic damit Methoden aus der Modulklasse aufgerufen werden können
                        //da CreateInstance uns trotz bekanntem Typ ein Object zurückgibt
                        //und wir den Typ der Instanz nicht manuell festlegen wollen/können
                        try
                        {
                            dynamic f = lib.CreateInstance(typ.ToString());
                            moduleListe.Add(f);
                            //f.Show(dockPanelMain, DigitalRune.Windows.Docking.DockState.Floating);
                            f.Show(dockPanelMain, DigitalRune.Windows.Docking.DockState.DockLeftAutoHide);
                            f.AutoHidePortion = 0.5;

                            editor.RegisterModule(f);

                            ToolStripMenuItem newItem = new ToolStripMenuItem(f.Text);
                        }
                        catch (System.Exception ex)
                        {
                            //MessageBox.Show("asdfasdf"+ex.Message);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Menüpunkte der geladenen Modulformen hinzufügen zum aktivieren/deaktivieren der Modulform
        /// </summary>
        private void BuildViewMenuItems()
        {
            ToolStripMenuItem[] items = new ToolStripMenuItem[moduleListe.Count];
            for (int i = 0; i < items.Length; i++)
            {
                items[i] = new ToolStripMenuItem();
                items[i].Name = moduleListe[i].Text;
                items[i].Text = moduleListe[i].Text;
                items[i].CheckOnClick = true;
                items[i].Checked = true;
                items[i].Click += new EventHandler(MenuItemClickHandler);
            }
            MenuItem_View.DropDownItems.AddRange(items);
        }
        /// <summary>
        /// Fehler aus dem Script werden hier abgefangen und in dem Error-Logfenster angezeigt
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e">Fehlermeldung</param>
        void editor_ExceptionThrown(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            if (InvokeRequired)
            {
                editor_ExceptionThrownDelegate d = new editor_ExceptionThrownDelegate(editor_ExceptionThrown);
                this.Invoke(d, new object[] { sender, e });
                return;
            }
            errorForm.SetErrorText(e.Exception.Message);
            StatusButton_ErrorStatus.Image = imageList_ErrorLights.Images[2];
        }
        /// <summary>
        /// Abonniertes Event aus der User-Account Form wenn sich ein User eingeloggt hat
        /// </summary>
        /// <param name="objSender"></param>
        /// <param name="e">Name und Userlevel des angemeldeten Users werden übergeben</param>
        public void userAccount_UserLogedIn(Object objSender, userEventArgs e)
        {
            currentUser.userName = e.User;
            currentUser.userLevel = e.UserLevel;
            try
            {
                foreach (dynamic frm in moduleListe)
                {
                    frm.setAdminLevel = e.UserLevel;
                }
            }
            catch { }
            this.Text = "Cube - " + currentUser.userName + " " + Properties.Resources.LoginString;
        }

        #endregion

        #region Events der Hauptform und ihrer statisch erzeugten Fenster
        /// <summary>
        /// Wenn ein Menüeintrag zu einem geladenen Modul geklickt wird, entsprechende Modulform aktivieren/deaktiveren
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MenuItemClickHandler(object sender, EventArgs e)
        {
            ToolStripMenuItem clickedItem = (ToolStripMenuItem)sender;
            if (clickedItem.Checked == true)
            {
                for (int i = 0; i < moduleListe.Count; i++)
                {
                    if (moduleListe[i].Text == clickedItem.Text)
                    {
                        moduleListe[i].Show();
                        moduleListe[i].BringToFront();
                        moduleListe[i].WindowState = FormWindowState.Normal;
                    }
                }
            }
            else
            {
                for (int i = 0; i < moduleListe.Count; i++)
                {
                    if (moduleListe[i].Text == clickedItem.Text)
                        moduleListe[i].Hide();
                }
            }
        }
        /// <summary>
        /// Wenn die Tree-Übersichtsform mit den dyn.geladenen Modulen geschlossen wird MenuItem.Checked auf false setzen
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void treeForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            showModulesMenuItem.Checked = false;
        }
        /// <summary>
        /// Tree-Übersichtsform anzeigen/ausblenden
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void showModulesMenuItem_Click(object sender, EventArgs e)
        {
            if (showModulesMenuItem.Checked)
            {
                treeForm.Visible = true;
                treeForm.Show(dockPanelMain, DigitalRune.Windows.Docking.DockState.DockLeft);
            }
            else
            {
                treeForm.Show(dockPanelMain, DigitalRune.Windows.Docking.DockState.DockLeftAutoHide);
                editor.Focus();
            }
        }
        /// <summary>
        /// Schließt das Hauptprogramm
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        /// <summary>
        /// Anzeigen der User-Account Verwaltung
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void loginToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                userAccount.clearText();
                Application.DoEvents();
                userAccount.Show();
                userAccount.WindowState = FormWindowState.Normal;
                userAccount.BringToFront();
            }
            catch { }
        }
        /// <summary>
        /// Anzeigen der Hilfeform
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripMenuItem_Help_Click(object sender, EventArgs e)
        {
            try
            {
                if (toolStripMenuItem_Help.Checked)
                    helpForm.Show(dockPanelMain, DigitalRune.Windows.Docking.DockState.Floating);
                else
                    helpForm.Hide();
            }
            catch { }
        }
        /// <summary>
        /// Error-Logfenster aktivieren/deaktiveren
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StatusButton_ErrorStatus_Click(object sender, EventArgs e)
        {
            if (errorForm.Visible == false)
            {
                //Exception Log-Fenster aktivieren
                errorForm.Show(this);
                Application.DoEvents();
                errorForm.TopMost = true;
                errorForm.Top = this.Height - errorForm.Height - statusStrip1.Height - SystemInformation.CaptionHeight+6;
                errorForm.Left = 0 - errorForm.Width;
                for (int i = 0; i < errorForm.Width; i++)
                {
                    errorForm.Left++;                    
                }
            }
            else
            {
                errorForm.TopMost = true;
                //Log-Fenster wieder einfahren
                int maxCount = errorForm.Left + errorForm.Width;
                for (int i = 0; i < maxCount; i++)
                {
                    errorForm.Left--;
                }
                errorForm.Hide();
                //Wenn das Log-Fenster deaktiviert wird, Ampel-Status wieder auf grün setzen
                StatusButton_ErrorStatus.Image = imageList_ErrorLights.Images[0];
            }
        }
        /// <summary>
        /// Event zum deaktiveren des Error-Logfensters
        /// Wird gefeuert wenn auf der Error-Form der DropDown-Btn gedrückt wurde
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void errorForm_ClosedClicked(object sender, EventArgs e)
        {
            //Log-Fenster wieder einfahren
            int maxCount = errorForm.Left + errorForm.Width;
            for (int i = 0; i < maxCount; i++)
            {
                errorForm.Left--;
            }
            errorForm.Hide();
            //Wenn das Log-Fenster deaktiviert wird, Ampel-Status wieder auf grün setzen
            StatusButton_ErrorStatus.Image = imageList_ErrorLights.Images[0];
        }
        #endregion

        #region Spracheinstellungen ändern
        private void germanToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                File.WriteAllText("language.txt", "de-DE");
                Application.Restart();
            }
            catch 
            {
                MessageBox.Show(Properties.Resources.CantWriteFileString);
            }
        }

        private void englishToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                File.WriteAllText("language.txt", "en-US");
                Application.Restart();
            }
            catch
            {
                MessageBox.Show(Properties.Resources.CantWriteFileString);
            }
        }
        #endregion

    }
}
